﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using LibraryONTrack.dto;

namespace LibraryONTrack.Persistence.DataMappers
{
	class OverdueBookMapper : IDataMapper
	{
		private bool _isInitialized = false;
		private int _ordinal_book_id;
		private int _ordinal_book_title;
		private int _ordinal_notice_count;
		private int _ordinal_still_overdue_ind;
		private int _ordinal_last_notice_sent_unixtime;
		private int _ordinal_borrower_id;
		private int _ordinal_borrower_name;
		private int _ordinal_teacher_id;
		private int _ordinal_teacher_name;

		private void InitializeMapper(IDataReader reader)
		{
			PopulateOrdinals(reader);
			_isInitialized = true;
		}

		public void PopulateOrdinals(IDataReader reader)
		{
			_ordinal_book_id = reader.GetOrdinal("book_id");
			_ordinal_book_title = reader.GetOrdinal("title");
			_ordinal_notice_count = reader.GetOrdinal("notice_count");
			_ordinal_still_overdue_ind = reader.GetOrdinal("still_overdue_ind");
			_ordinal_last_notice_sent_unixtime = reader.GetOrdinal("last_notice_sent_unixtime");		
			_ordinal_borrower_id = reader.GetOrdinal("borrower_id");
			_ordinal_borrower_name = reader.GetOrdinal("borrower_name");
			_ordinal_teacher_id = reader.GetOrdinal("teacher_id");
			_ordinal_teacher_name = reader.GetOrdinal("teacher_name");
		}

		public object GetData(System.Data.IDataReader reader)
		{
			// This is where we define the mapping between the object properties and the 
			// data columns. The convention that should be used is that the object property 
			// names are exactly the same as the column names. However if there is some 
			// compelling reason for the names to be different the mapping can be defined here.

			// We assume the reader has data and is already on the row that contains the data 
			//we need. We don't need to call read. As a general rule, assume that every field must 
			//be null  checked. If a field is null then the nullvalue for that  field has already 
			//been set by the DTO constructor, we don't have to change it. 
			if (!_isInitialized)
			{
				InitializeMapper(reader);
			}

			OverdueBook dto = (OverdueBook)GetInstance();

			// Now we can load the data
			dto.Book = new Book(reader.GetInt64(_ordinal_book_id), reader.GetString(_ordinal_book_title));
			
			if (!reader.IsDBNull(_ordinal_notice_count))
			{
				dto.NoticeCount = reader.GetInt32(_ordinal_notice_count);
			}

			if (!reader.IsDBNull(_ordinal_still_overdue_ind))
			{
				dto.StillOverdue = reader.GetBoolean(_ordinal_still_overdue_ind);
			}

			if (!reader.IsDBNull(_ordinal_last_notice_sent_unixtime))
			{
				dto.LastNoticeSentDateTime =
					LibraryONTrack.dao.OverdueBookDAO.ConvertFromUnixTimestamp(reader.GetInt32(_ordinal_last_notice_sent_unixtime));
			}

			long teacherId = reader.GetInt64(_ordinal_teacher_id);

			dto.Borrower = new Student(reader.GetInt64(_ordinal_borrower_id), reader.GetString(_ordinal_borrower_name), teacherId);

			dto.Teacher = new Teacher(teacherId, reader.GetString(_ordinal_teacher_name));

			return dto;
		}
				
		public int GetRecordCount(System.Data.IDataReader reader)
		{
			Object count = reader["RecordCount"];
			return count == null ? 0 : Convert.ToInt32(count);			
		}


		public object GetInstance()
		{
			return new OverdueBook();
		}
	}
}
